package com.meme.io.editor;


import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Attr;
import org.w3c.dom.Text;


import com.meme.util.XmlUtil;
import com.meme.util.FileUtil;

import com.meme.editor.model.sprite2d.*;

public class Sprite2dXmlFileWriter 
{
	String mSprite2dXmlFilename;

	public Document writeToXmlDocument (Sprite2dFile sprite2dFile)
	{
		Document document = XmlUtil.createNewDocument();
		
		// ...
		writeSprite2dFile (document, sprite2dFile);
		
		return document;
	}
	
	public void writeToFile (Sprite2dFile sprite2dFile, String filename)
	{	
		if ( ! filename.endsWith("." + Sprite2dFile.getFileExtension()) )
			filename = filename + "." + Sprite2dFile.getFileExtension();
		
		mSprite2dXmlFilename = filename;
		
		Document document = writeToXmlDocument (sprite2dFile);

		XmlUtil.writeXmlFile(document, filename);
		
		sprite2dFile.setHostFilename (filename);
		sprite2dFile.commitModifications();
	}
	
//---------------------------------------------------------------------------	
//
//---------------------------------------------------------------------------	
	
	void writeSprite2dFile (Document document, Sprite2dFile sprite2dFile)
	{
		Element sprite2dElement = document.createElement("Sprite2d");
		document.appendChild(sprite2dElement);

		sprite2dElement.setAttribute("version", "1.0");
		
		
		// module image set
		{			
			Element element = document.createElement("ModuleImageSet");	
			sprite2dElement.appendChild(element);

			Sprite2dFile.ModuleImageSet moduleImageSet = sprite2dFile.getModuleImageSet();
			element.setAttribute("name", moduleImageSet.getName());
			
			for (int i = 0; i < moduleImageSet.getChildrenCount(); ++ i)
			{
				writeModuleImage (document, element, (ModuleImage) moduleImageSet.getChildByIndex(i) );
			}
		}
		
		// pure module group set
		{			
			Element element = document.createElement("PureModuleGroupSet");	
			sprite2dElement.appendChild(element);

			Sprite2dFile.PureModuleGroupSet pureModuleGroupSet = sprite2dFile.getPureModuleGroupSet();
			element.setAttribute("name", pureModuleGroupSet.getName());
			
			for (int i = 0; i < pureModuleGroupSet.getChildrenCount(); ++ i)
			{
				writePureModuleGroup (document, element, (PureModuleGroup) pureModuleGroupSet.getChildByIndex(i) );
			}
		}
		
		// composited module group set
		{			
			Element element = document.createElement("CompositedModuleGroupSet");		
			sprite2dElement.appendChild(element);
			
			Sprite2dFile.CompositedModuleGroupSet compositedModuleGroupSet = sprite2dFile.getCompositedModuleGroupSet();
			element.setAttribute("name", compositedModuleGroupSet.getName());

			for (int i = 0; i < compositedModuleGroupSet.getChildrenCount(); ++ i)
			{
				writeCompositedModuleGroup (document, element, (CompositedModuleGroup) compositedModuleGroupSet.getChildByIndex(i) );
			}
		}
		
		// animated module group set
		{			
			Element element = document.createElement("AnimatedModuleGroupSet");		
			sprite2dElement.appendChild(element);

			Sprite2dFile.AnimatedModuleGroupSet animatedModuleGroupSet = sprite2dFile.getAnimatedModuleGroupSet();
			element.setAttribute("name", animatedModuleGroupSet.getName());
			
			for (int i = 0; i < animatedModuleGroupSet.getChildrenCount(); ++ i)
			{
				writeAnimatedModuleGroup (document, element, (AnimatedModuleGroup) animatedModuleGroupSet.getChildByIndex(i) );
			}
		}

		
		// predefined model set
		{			
			Element element = document.createElement("PredeinedModelSet");
			sprite2dElement.appendChild(element);
			
			Sprite2dFile.ModelSet predefinedModelSet = sprite2dFile.getPredefinedModelSet();
			element.setAttribute("name", predefinedModelSet.getName());

			for (int i = 0; i < predefinedModelSet.getChildrenCount(); ++ i)
			{
				writeSprite2dModel (document, element, (Sprite2dModel) predefinedModelSet.getChildByIndex(i) );
			}
		}
		
		// tile palette set
		{
			Element element = document.createElement("TilePaletteSet");
			sprite2dElement.appendChild(element);
			
			Sprite2dFile.TilePaletteSet tilePaletteSet = sprite2dFile.getTilePaletteSet();
			element.setAttribute("name", tilePaletteSet.getName());
			
			for (int i = 0; i < tilePaletteSet.getChildrenCount(); ++ i)
			{
				writeTilePaletteSet (document, element, (Tiled2dPalette) tilePaletteSet.getChildByIndex(i));
			}
		}
		
		// tiled background
		{
			Element element = document.createElement("Tiled2dBackgroundSet");
			sprite2dElement.appendChild(element);
			
			Sprite2dFile.TiledBackgroundSet tiledBackgroundSet = sprite2dFile.getTiledBackgroundSet();
			element.setAttribute("name", tiledBackgroundSet.getName());
			
			for (int i = 0; i < tiledBackgroundSet.getChildrenCount(); ++ i)
			{
				writeTiledBackgroundSet (document, element, (Tiled2dBackground) tiledBackgroundSet.getChildByIndex(i));
			}
		}
	}
	
	void writeModuleImage (Document document, Element parent, ModuleImage moduleImage)
	{
		Element element = document.createElement("ModuleImage");	
		parent.appendChild (element);

		element.setAttribute("name", moduleImage.getName());
		element.setAttribute("image_url", FileUtil.getRelativePathFilename(moduleImage.getImageFilename(), mSprite2dXmlFilename));
	}

	void writePureModuleGroup (Document document, Element parent, PureModuleGroup pureModuleGroup)
	{
		Element element = document.createElement("PureModuleGroup");	
		parent.appendChild (element);

		element.setAttribute("name", pureModuleGroup.getName());
		element.setAttribute("image_ref", pureModuleGroup.getModuleImage() == null ? "" : pureModuleGroup.getModuleImage().getName() );
		
		for (int i = 0; i < pureModuleGroup.getChildrenCount(); ++ i)
		{
			writePureModule (document, element, (PureModule) pureModuleGroup.getChildByIndex(i) );
		}
	}
	
	void writePureModule (Document document, Element parent, PureModule pureModule)
	{
		Element element = document.createElement("PureModule");	
		parent.appendChild (element);

		element.setAttribute("name", pureModule.getName());		
		element.setAttribute("x", "" + pureModule.getX());
		element.setAttribute("y", "" + pureModule.getY());
		element.setAttribute("w", "" + pureModule.getWidth());
		element.setAttribute("h", "" + pureModule.getHeight());
	}
	
	void writeCompositedModuleGroup (Document document, Element parent, CompositedModuleGroup compositedModuleGroup)
	{
		Element element = document.createElement("CompositedModuleGroup");	
		parent.appendChild (element);

		element.setAttribute("name", compositedModuleGroup.getName());
		
		for (int i = 0; i < compositedModuleGroup.getChildrenCount(); ++ i)
		{
			writeCompositedModule (document, element, (CompositedModule) compositedModuleGroup.getChildByIndex(i) );
		}
	}
	
	void writeCompositedModule (Document document, Element parent, CompositedModule compositedModule)
	{
		Element element = document.createElement("CompositedModule");	
		parent.appendChild (element);

		element.setAttribute("name", compositedModule.getName());
		
		for (int i = 0; i < compositedModule.getChildrenCount(); ++ i)
		{
			writeModulePart (document, element, (ModulePart) compositedModule.getChildByIndex(i) );
		}
	}
	
	void writeModulePart (Document document, Element parent, ModulePart modulePart)
	{
		Element element = document.createElement("ModulePart");	
		parent.appendChild (element);

		element.setAttribute("name", modulePart.getName());
		element.setAttribute("module_ref", modulePart.getModule() == null ? "" : modulePart.getModule().getParent().getParent().getName() + "/" + modulePart.getModule().getParent().getName() + "/" + modulePart.getModule().getName() );
		element.setAttribute("offset_x", "" + modulePart.getOffsetX());
		element.setAttribute("offset_y", "" + modulePart.getOffsetY());
		element.setAttribute("flip_x", modulePart.isFlipX() ? "true" : "false");
		element.setAttribute("flip_y", modulePart.isFlipY() ? "true" : "false");
		element.setAttribute("palette", "" + modulePart.getPaletteID());
		element.setAttribute("flags", "" + modulePart.getFlags() );
	}
	
	void writeAnimatedModuleGroup (Document document, Element parent, AnimatedModuleGroup animatedModuleGroup)
	{
		Element element = document.createElement("AnimatedModuleGroup");	
		parent.appendChild (element);

		element.setAttribute("name", animatedModuleGroup.getName());
		
		for (int i = 0; i < animatedModuleGroup.getChildrenCount(); ++ i)
		{
			writeAnimatedModule (document, element, (AnimatedModule) animatedModuleGroup.getChildByIndex(i) );
		}
	}
	
	void writeAnimatedModule (Document document, Element parent, AnimatedModule animatedModule)
	{
		Element element = document.createElement("AnimatedModule");	
		parent.appendChild (element);

		element.setAttribute("name", animatedModule.getName());
		
		for (int i = 0; i < animatedModule.getChildrenCount(); ++ i)
		{
			writeModuleSequence (document, element, (ModuleSequence) animatedModule.getChildByIndex(i) );
		}
	}
	
	void writeModuleSequence (Document document, Element parent, ModuleSequence moduleSequence)
	{
		Element element = document.createElement("ModuleSequence");	
		parent.appendChild (element);

		element.setAttribute("name", moduleSequence.getName());
		element.setAttribute("module_ref", moduleSequence.getModule() == null ? "" : moduleSequence.getModule().getParent().getParent().getName() + "/" + moduleSequence.getModule().getParent().getName() + "/" + moduleSequence.getModule().getName() );
		element.setAttribute("offset_x", "" + moduleSequence.getOffsetX());
		element.setAttribute("offset_y", "" + moduleSequence.getOffsetY());
		element.setAttribute("flip_x", moduleSequence.isFlipX() ? "true" : "false");
		element.setAttribute("flip_y", moduleSequence.isFlipY() ? "true" : "false");
		element.setAttribute("palette", "" + moduleSequence.getPaletteID());
		element.setAttribute("flags", "" + moduleSequence.getFlags() );
		element.setAttribute("duration", "" + moduleSequence.getDuration() );
	}
	
	void writeSprite2dModel (Document document, Element parent, Sprite2dModel sprite2dModel)
	{
		
	}
	
	void writeTilePaletteSet (Document document, Element parent, Tiled2dPalette tilePalette)
	{
		Element element = document.createElement("TilePalette");
		parent.appendChild (element);
		
		element.setAttribute("name", tilePalette.getName());
		element.setAttribute("cell_width", "" + tilePalette.getCellWidth());
		element.setAttribute("cell_height", "" + tilePalette.getCellHeight());
		element.setAttribute("cell_rows", "" + tilePalette.getCellRows());
		element.setAttribute("cell_cols", "" + tilePalette.getCellCols());
		
		for (int i = 0; i < tilePalette.getChildrenCount(); ++ i)
		{
			writeTiled2dModule (document, element, (Tiled2dModule) tilePalette.getChildByIndex(i) );
		}
	}
	
	void writeTiled2dModule (Document document, Element parent, Tiled2dModule tiled2dModule)
	{
		Element element = document.createElement("Tiled2dModule");
		parent.appendChild (element);
		
		element.setAttribute("name", tiled2dModule.getName());
		element.setAttribute("module_ref", tiled2dModule.getModule() == null ? "" : tiled2dModule.getModule().getParent().getParent().getName() + "/" + tiled2dModule.getModule().getParent().getName() + "/" + tiled2dModule.getModule().getName());
		element.setAttribute("flip_x", tiled2dModule.isFlipX() ? "true" : "false" );
		element.setAttribute("flip_y", tiled2dModule.isFlipY() ? "true" : "false" );
		element.setAttribute("palette", "" + tiled2dModule.getPaletteID() );

	}

	void writeTiledBackgroundSet (Document document, Element parent, Tiled2dBackground tiledBackground)
	{
		Element element = document.createElement("Tiled2dBackground");
		parent.appendChild (element);
		
		element.setAttribute("name", tiledBackground.getName());
		element.setAttribute("cell_width", "" + tiledBackground.getCellWidth());
		element.setAttribute("cell_height", "" + tiledBackground.getCellHeight());
		element.setAttribute("cell_rows", "" + tiledBackground.getCellRows());
		element.setAttribute("cell_cols", "" + tiledBackground.getCellCols());
		
		for (int i = 0; i < tiledBackground.getChildrenCount(); ++ i)
		{
			writeTiled2dLayer (document, element, (Tiled2dLayer) tiledBackground.getChildByIndex(i) );
		}
	}

	void writeTiled2dLayer (Document document, Element parent, Tiled2dLayer tiled2dLayer)
	{
		Element element = document.createElement("Tiled2dLayer");
		parent.appendChild (element);
		
		element.setAttribute("name", tiled2dLayer.getName());
		
		StringBuffer cellValuesString = new StringBuffer (100000);

		for (int row = 0; row < tiled2dLayer.getCellRows(); ++ row)
		{
			for (int col = 0; col < tiled2dLayer.getCellCols(); ++ col)
			{
				Tiled2dLayerCell layerCell = tiled2dLayer.getLayerCellByPos (row, col);
				Tiled2dModule tile = (Tiled2dModule) layerCell.getModule();
				if ( tile != null )
				{
					cellValuesString.append (tile.getParent().getIndex() + "-");
					cellValuesString.append (tile.getRow() + "-");
					cellValuesString.append (tile.getCol() + "-");
				}
				cellValuesString.append (":" + layerCell.getPaletteID() + ":");
				if ( layerCell.isFlipX() )
					cellValuesString.append ('x');
				if ( layerCell.isFlipY() )
					cellValuesString.append ('y');
				
				cellValuesString.append (",");
			}
		}
		
		Text text = document.createTextNode(cellValuesString.toString());
		element.appendChild(text);
	}
}
